// tcp/client/main.go

package tcp_helper

import (
	"fmt"
	"net"
	"sync"
	"time"
)

const heatBeatInterval = 500 * time.Millisecond
const reConnectInterval = 1 * time.Second

type Client struct {
	BaseClient
	close_conn_cond *sync.Cond //连接断开条件
}

func CreateClient(id []byte) *Client {
	cli := &Client{}
	cli.id = id
	cli.readed_pkgs = make(chan *Package)
	cli.to_write_pkgs = make(chan *Package, SendPackageCacheSize)
	cli.read_buf = []byte{}
	cli.write_buf = []byte{}
	cli.close_conn_cond = sync.NewCond(&cli.lock)
	cli.close_conn_callback = cli.close_conn
	return cli
}

//持续发送心跳包, 一个连接结束了此函数也会结束
func (cli *Client) SendHeartbeat() {
	old_conn := cli.GetConn() //记录初始连接，如果中途重连了，此函数不服务两个连接
	for {
		if cli.GetConn() != old_conn {
			//断开或者已重连
			return
		}

		ret := cli.Send(cli.id, []byte{}) //心跳包
		if ret == -1 {
			//连接断开
			return
		} else if ret == -2 {
			//发送缓存已满
		}
		time.Sleep(heatBeatInterval)
	}
}

func (cli *Client) HandleConn(conn net.Conn) {
	// 建立连接后，先发送一个心跳包，表明身份
	cli.SetConn(conn)
	go cli.handleSend()
	go cli.SendHeartbeat()
	go cli.handleRead()
}

//连接
func (cli *Client) Connect() {
	conn, err := net.Dial("tcp", "127.0.0.1:20000")
	if err != nil {
		//连接失败
		fmt.Println("connect error :", err)
		return
	}
	cli.HandleConn(conn)
}

//断开连接回调
func (cli *Client) close_conn() {
	cli.close_conn_cond.Broadcast()
}

//运行。不断重连
func (cli *Client) Run() {
	for {
		//连接
		cli.Connect()

		{
			//等到断开连接
			cli.lock.Lock()
			defer cli.lock.Unlock()
			if cli.conn != nil {
				cli.close_conn_cond.Wait()
			}
		}

		time.Sleep(reConnectInterval)
	}
}
